#ifndef _LONGGUI_WINDOW_H
#define _LONGGUI_WINDOW_H


#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

enum
{
    MSG_CREATE,
    MSG_TIMER,
    MSG_CHAR,
    MSG_KEYUP,
    MSG_KEYLONGPRESS,
    MSG_KEYDOWN,
    MSG_CHANGESIZE,
    MSG_PAINT,
    MSG_GETTEXTLENGTH,
    MSG_GETTEXT,
    MSG_SETTEXT,
    MSG_DESTROY,
    MSG_GETCTRLCLASSINFO  =  0x016B,
    MSG_NEWCTRLINSTANCE,
    MSG_REMOVECTRLINSTANCE,
    MSG_GETACTIVEMAIN,
    MSG_ADDNEWMAINWIN,
    MSG_REMOVEMAINWIN,

    MSG_USER,
};

/**
 * \defgroup styles Window styles
 * @{
 */

/**
* \def WS_NONE
* \brief None style.
*
* \def WS_ABSSCRPOS
* \brief Creates a main window whose position is based on absolute
*        screen coordinates.
*
* \def WS_CAPTION
* \brief Creates a main window with caption.
*
* \def WS_CHILD
* \brief Indicates the window is a child.
*
* \def WS_SYSMENU
* \brief Creates a main window with system menu.
*
* \def WS_VISIBLE
* \brief Creates a window initially visible.
*
* \def WS_DISABLED
* \brief Creates a window initially disabled.
*
* \def WS_BORDER
* \brief Creates a window with border.
*
* \def WS_THICKFRAME
* \brief Creates a window with thick frame.
*
* \def WS_THINFRAME
* \brief Creates a window with thin frame.
*
* \def WS_VSCROLL
* \brief Creates a window with vertical scroll bar.
*
* \def WS_HSCROLL
* \brief Creates a window with horizontal scroll bar.
*
* \def WS_MINIMIZEBOX
* \brief Creates a window with minimizing box on caption.
*
* \def WS_MAXIMIZEBOX
* \brief Creates a window with maximizing box on caption.
*
* \def WS_GROUP
* \brief Indicates the control is the leader of a group.
*
* \def WS_TABSTOP
* \brief Indicates the user can set the input focus to the control by
*        using Tab key.
*/
enum
{
    WS_NONE         = 0x00000000L,
    WS_OVERLAPPED   = 0x00000000L, /*Not supported*/
    WS_ABSSCRPOS    = 0x80000000L,
    WS_CHILD        = 0x40000000L,
    WS_CAPTION      = 0x20000000L,
    WS_SYSMENU      = 0x10000000L,
    WS_VISIBLE      = 0x08000000L,
    WS_DISABLED     = 0x04000000L,
    WS_MINIMIZE     = 0x02000000L,
    WS_MAXIMIZE     = 0x01000000L,
    WS_DLGFRAME     = 0x00800000L,
    WS_BORDER       = 0x00400000L,
    WS_THICKFRAME   = 0x00200000L,
    WS_THINFRAME    = 0x00100000L,
    WS_VSCROLL      = 0x00080000L,
    WS_HSCROLL      = 0x00040000L,
    WS_MINIMIZEBOX  = 0x00020000L,
    WS_MAXIMIZEBOX  = 0x00010000L,
    WS_GROUP        = 0x00020000L,
    WS_TABSTOP      = 0x00010000L,
};

/**
 * Structure defines a window class
 */
typedef struct _WNDCLASS
{
    /** The class name */
    char*   spClassName;

    /** Window style for all instances of this window class */
    DWORD   dwStyle;

    /** Window callback procedure of all instances of this window class */
    int     (*WinProc) (HWND, int, WPARAM, LPARAM);
} WNDCLASS;
typedef WNDCLASS* PWNDCLASS;

/**
 * \var typedef int (* WNDPROC)(HWND, int, WPARAM, LPARAM)
 * \brief Type of the window callback procedure.
 */
typedef int (* WNDPROC)(HWND, int, WPARAM, LPARAM);

extern HWND __lg_hwnd_desktop;

/**
 * \def HWND_DESKTOP
 * \brief Desktop window handle.
 */
#define HWND_DESKTOP        __lg_hwnd_desktop


/**
 * \def HWND_NULL
 * \brief Null window handle.
 */
#define HWND_NULL           0

/**
 * \def HWND_INVALID
 * \brief Invalid window handle.
 */
#define HWND_INVALID        0xFFFFFFFF


typedef struct _DLGTEMPLATE
{
    /** Dialog box style */
    DWORD       dwStyle;
    /** Dialog box position */
    int         x, y, w, h;
    /** Dialog box caption */
    const char* caption;
} DLGTEMPLATE;
typedef DLGTEMPLATE* PDLGTEMPLATE;

/**
 * \fn HWND GUIAPI CreateMainWindowIndirectParam (PDLGTEMPLATE pDlgTemplate, \
 *               HWND hOwner, WNDPROC WndProc, LPARAM lParam)
 * \brief Uses a dialog template to create a modeless main window and
 *        controls in it, and pass a parameter to the window procedure.
 *
 * This function uses a dialog template pointed to by \a pDlgTemplate
 * to create a modeless main window and controls in it. The parameter
 * specified by \a lParam will be passed to the window procedure as the
 * second paramter of MSG_INITDIALOG message.
 *
 * \param pDlgTemplate The pointer to a DLGTEMPLATE structure.
 * \param WndProc The window procedure of the new main window.
 *
 * \return Handle to the new main window, HWND_INVALID on error.
 *
 * \sa DestroyMainWindowIndirect, DLGTEMPLATE
 */
HWND GUIAPI CreateMainWindowIndirectParam (PDLGTEMPLATE pDlgTemplate,
                 WNDPROC WndProc);

/**
 * \fn BOOL GUIAPI DestroyMainWindowIndirect (HWND hWnd)
 * \brief Destroys a main window.
 *
 * This function destroys the main window specified by \a hWnd.
 * It does not release all system resource used by the main window.
 * You should call \a MainWindowThreadCleanup to destroy the main window
 * actually.
 *
 * \param hWnd The handle to the main window.
 * \return TRUE on success, FALSE on error.
 *
 * \sa MainWindowThreadCleanup
 *
 * Example:
 *
 * \include destroymainwindow.c
 */
BOOL GUIAPI DestroyMainWindowIndirect (HWND hWnd);

int GUIAPI PreDefMainWinProc (HWND hWnd, int message,
                WPARAM wParam, LPARAM lParam);

int GUIAPI PreDefControlProc (HWND hWnd, int message,
                WPARAM wParam, LPARAM lParam);

/**
 * \fn int DefaultWindowProc (HWND hWnd, int message, \
                WPARAM wParam, LPARAM lParam)
 * \brief The default window callback procedure.
 *
 * This window procedure can be used for main windows, dialog boxes,
 * and child windows.
 *
 * This function is the default window callback procedure.
 * You should call this function for all messages you do not want to handle
 * in your window procedure.
 *
 * \param hWnd The handle to the window.
 * \param message The message identifier.
 * \param wParam The first parameter of the message.
 * \param lParam The second parameter of the message.
 */
int GUIAPI DefaultWindowProc (HWND hWnd, int message,
                WPARAM wParam, LPARAM lParam);

/**
 * \fn void GUIAPI DestroyAllControls (HWND hWnd)
 * \brief Destroys all controls in a window.
 *
 * This function destroys all controls (child windows) in a window.
 *
 * \param hWnd The handle to the window.
 *
 * \sa DestroyWindow
 */
void GUIAPI DestroyAllControls (HWND hWnd);

/**
* \fn HWND GUIAPI CreateWindow (const char* spClassName, \
*                const char* spCaption, DWORD dwStyle, \
*               int id, int x, int y, int w, int h, HWND hParentWnd)
* \brief Creates a child window with extended style.
*
* This function creates a child window (also known as "control") with
* extended style. It specifies the window class, the window title,
* the window style, the window extended style, the initial position,
* and the size of the window.  The function also specifies the
* window's parent or owner.
*
* \param spClassName The class name of the control.
* \param spCaption The caption of the control.
* \param dwStyle The control style.
* \param id The identifier of the control.
* \param x x,y: The initial position of the control in the parent window.
* \param y x,y: The initial position of the control in the parent window.
* \param w The initial width of the control.
* \param h The initial height of the control.
* \param hParentWnd The handle to the parent window.
*
* \return The handle to the new control, HWND_INVALID on error.
*
* \sa CreateMainWindow, CTRLDATA
*
* Example:
*
* \include createwindow.c
*/
HWND GUIAPI CreateWindow (const char* spClassName,
                const char* spCaption, DWORD dwStyle,
                int x, int y, int w, int h, HWND hParentWnd);

/**
 * \fn BOOL GUIAPI DestroyWindow (HWND hWnd)
 * \brief Destroys a specified control.
 *
 * This function destroys the specified control \a hWnd, which is created
 * by \a CreateWindowEx.
 *
 * \param hWnd The handle to the control.
 * \return TRUE on success, FALSE on error.
 *
 * \sa CreateWindowEx
 */
BOOL GUIAPI DestroyWindow (HWND hWnd);

/**
 * \var WNDPROC __lg_def_proc[2]
 * \brief The default window callback procedure array
 *
*/
extern WNDPROC __lg_def_proc[2];

/**
 * \def DefaultMainWinProc
 * \brief Is the default main window callback procedure.
 *
 * This function is the default main window callback procedure.
 * You should call this function for all messages, you do not want to handle
 * in your main window procedure.
 *
 * \param hWnd The handle to the window.
 * \param message The message identifier.
 * \param wParam The first parameter of the message.
 * \param lParam The second parameter of the message.
 *
 */
#define DefaultMainWinProc (__lg_def_proc[0])

/**
 * \def DefaultControlProc
 * \brief The default control callback procedure.
 *
 * This function is the default control callback procedure.
 * You should call this function for all messages, you do not want to handle
 * in your own control procedure.
 *
 * \param hWnd The handle to the window.
 * \param message The message identifier.
 * \param wParam The first parameter of the message.
 * \param lParam The second parameter of the message.
 */
#define DefaultControlProc (__lg_def_proc[1])

/**
 * \fn HWND GUIAPI GetActiveWindow (void)
 * \brief Retrieves the main window handle to the active main window.
 *
 * This function retrives the main window handle to the active main window
 * which receives the input.
 *
 * \return The handle to the active main window.
 *
 * \sa SetActiveWindow, GetFocusChild
 */
HWND GUIAPI GetActiveWindow (void);

/**
 * \fn BOOL GUIAPI EnableWindow (HWND hWnd, BOOL fEnable)
 * \brief Enables of disables a window.
 *
 * This function enables or disables mouse and keyboard input
 * to the specified window \a hWnd. When input is disabled, the window
 * does not receive input such as mouse clicks and key presses.
 * When input is enabled, the window receives all input.
 *
 * \param hWnd The handle to the window.
 * \param fEnable Indicates whether to enable or disable the window,
 *        TRUE for enable.
 * \return The old enable state of the window.
 *
 * \sa IsWindowEnabled
 */
BOOL GUIAPI EnableWindow (HWND hWnd, BOOL fEnable);

/**
 * \fn BOOL GUIAPI IsWindowEnabled (HWND hWnd)
 * \brief Determines whether the specified window is enabled for mouse
 *        and keyboard input.
 *
 * This function returns the enable/disable state of the window specified by
 * \a hWnd.
 *
 * \param hWnd The handle to the window.
 *
 * \return The enable/disable state of the window, TRUE for enabled.
 *
 * \sa EnableWindow
 */
BOOL GUIAPI IsWindowEnabled (HWND hWnd);

/**
 * \fn int GUIAPI GetWindowTextLength (HWND hWnd)
 * \brief Retrieves the length of a window's text.
 *
 * This function retrieves the length, in characters, of the specified
 * window's text. The function retrieves the length of the text by sending
 * an MSG_GETTEXTLENGTH message to the window.
 *
 * \param hWnd The handle to the window.
 *
 * \return The length of the window's text.
 *
 * \sa GetWindowText
 */
int GUIAPI GetWindowTextLength (HWND hWnd);

/**
 * \fn int GUIAPI GetWindowText (HWND hWnd, char* spString, int nMaxLen)
 * \brief Copies the text of a window's into a buffer.
 *
 * This function copies the text of the specified window \a hWnd into the buffer
 * pointed to by \a spString. The function gets the window text by sending
 * an MSG_GETTEXT message to the window.
 *
 * \param hWnd The handle to the window.
 * \param spString The pointer to a buffer receives the text.
 * \param nMaxLen The maximal number of characters can be copied to the buffer.
 *
 * \return The length of the window text string.
 *
 * \sa GetWindowCaption, SetWindowText
 */
int GUIAPI GetWindowText (HWND hWnd, char* spString, int nMaxLen);

/**
 * \fn BOOL GUIAPI SetWindowText (HWND hWnd, const char* spString)
 * \brief Sets the text of a window.
 *
 * This function copies the string in the buffer pointed to by \a spString
 * to be the text of the specified window \a hWnd. The function sets
 * the window text by sending an MSG_SETTEXT message to the window.
 *
 * \param hWnd The handle to the window.
 * \param spString The pointer to the buffer.
 *
 * \return TRUE on success, otherwise FALSE.
 *
 * \sa SetWindowCaption, GetWindowText
 */
BOOL GUIAPI SetWindowText (HWND hWnd, const char* spString);

/**
 * \fn BOOL GUIAPI SetTimer (HWND hWnd, int id, unsigned int speed)
 * \brief Creates a timer with the specified timeout value.
 *
 * This function creates a timer with the specified timeout value \a speed.
 * Note that the timeout value is in unit of 10 ms.
 * When the timer expires, an MSG_TIMER message will be send to the
 * window \a hWnd if \a timer_proc is NULL, otherwise MiniGUI will call
 * \a timer_proc by passing \a hWnd, \a id, and the tick count when this
 * timer had expired to this callback procedure.
 *
 * \param hWnd The window receives the MSG_TIMER message. If \a timer_proc
 *        is not NULL, MiniGUI will call \a timer_proc instead sending
 *        MSG_TIMER message to this window. If you use timer callback
 *        procedure, \a hWnd can be any value you can pass.
 * \param id The identifier of the timer, will be passed to the window
 *        with MSG_TIMER message as the first parameter of the message.
 * \param speed The timeout value of the timer. Note that the timeout value
 *        is in unit of 1 ms.
 * \return TRUE on success, FALSE on error.
 *
 * \sa SetTimer, ResetTimerEx, KillTimer, MSG_TIMER
 *
 * \note You should set, reset, and kill a timer in the same thread if your
 *       MiniGUI is configured as MiniGUI-Threads.
 *
 * Example:
 *
 * \include settimer.c
 */
BOOL GUIAPI SetTimer (HWND hWnd, int id, unsigned int speed);

/**
 * \fn int GUIAPI KillTimer (HWND hWnd, int id)
 * \brief Destroys a timer.
 *
 * This function destroys the specified timer \a id.
 *
 * \param hWnd The window owns the timer.
 * \param id The identifier of the timer. If \a id equals or is less than 0,
 *        this function will kill all timers in the system.
 *
 * \return The number of actually killed timer.
 *
 * \sa SetTimer
 */
int GUIAPI KillTimer (HWND hWnd, int id);

/**
 * \fn BOOL GUIAPI GetClientRect(HWND hWnd, PRECT prc)
 * \brief Retrives the client rectangle of a window.
 *
 * This function retrives the coordinates of the client area of
 * the window specified by \a hWnd. The client coordinates specify
 * the upper-left and lower-right corners of the client area.
 * Because client coordinates are relative to the upper-left corner of
 * a window's client area, the coordinates of the upper-left corner
 * are always (0,0).
 *
 * \param hWnd The handle to the window.
 * \param prc The pointer to a RECT structure receives the client rectangle.
 *
 * \return TRUE on sucess, otherwise FALSE.
 *
 * \note Note that the coordinates of the upper-left corner are always zero.
 *
 * \sa MoveWindow
 */
BOOL GUIAPI GetClientRect(HWND hWnd, PRECT prc);

/**
 * \fn DWORD GUIAPI GetWindowStyle (HWND hWnd)
 * \brief Retrives the style of a window.
 *
 * This function retrives the style of the window specified by \a hWnd.
 *
 * \param hWnd The handle to the window.
 * \return The style of the window.
 *
 * \sa GetWindowExStyle
 */
DWORD GUIAPI GetWindowStyle (HWND hWnd);

/**
 * \fn const char* GUIAPI GetWindowCaption (HWND hWnd)
 * \brief Retrives the caption of a window.
 *
 * This function retrives the caption of the specified window \a hWnd.
 *
 * \param hWnd The handle to the window.
 *
 * \return The pointer to the caption string of the window.
 *
 * \sa SetWindowCaption
 */
const char* GUIAPI GetWindowCaption (HWND hWnd);


/**
 * The message structure.
 * \sa GetMessage, PostMessage, msgs
 */
typedef struct _MSG
{
    /** The handle to the window which receives this message. */
    HWND             hwnd;
    /** The message identifier. */
    int              message;
    /** The first parameter of the message (32-bit integer). */
    WPARAM           wParam;
    /** The second parameter of the message (32-bit integer). */
    LPARAM           lParam;
    /** Time*/
    unsigned int     time;
} MSG;
typedef MSG* PMSG;

#define QS_NOTIFYMSG        0x10000000
#define QS_DESKTIMER        0x20000000
#define QS_POSTMSG          0x40000000
#define QS_QUIT             0x80000000
#define QS_INPUT            0x01000000
#define QS_PAINT            0x02000000
#define QS_TIMER            0x0000FFFF
#define QS_EMPTY            0x00000000

/**
 * \def PM_NOREMOVE
 *
 * \sa PeekMessage PeekMessageEx
 */
#define PM_NOREMOVE     0x0000

/**
 * \def PM_REMOVE
 *
 * \sa PeekMessage PeekMessageEx PeekPostMessage
 */
#define PM_REMOVE       0x0001

/**
 * \def PM_NOYIELD
 *
 * \sa PeekMessage PeekMessageEx PeekPostMessage
 */
#define PM_NOYIELD      0x0002

/**
 * \fn BOOL PeekMessage (PMSG pMsg, HWND hWnd, \
 *                UINT uRemoveMsg)
 * \brief Peeks a message from the message queue of a main window
 *
 * This functions peek a message from the message queue of the window \a hWnd
 * and returns immediatly. Unlike \a GetMessage, this function does not wait
 * for a message.
 *
 * \param pMsg Pointer to the result message.
 * \param hWnd The handle to the window.
 * \param uRemoveMsg Whether remove the message from the message queue.
 *      Should be the following values:
 *      - PM_NOREMOVE\n
 *        Leave it in the message queue.
 *      - PM_REMOVE
 *        Remove it from the message queue.
 *      - PM_NOYIELD
 *        Nouse now.
 *
 * \return TRUE if there is a message peeked, or FALSE.
 *
 * \sa GetMessage, PeekPostMessage, HavePendingMessage, PostMessage
 */
BOOL GUIAPI PeekMessage (PMSG pMsg, HWND hWnd, UINT uRemoveMsg);

/**
 * \fn BOOL GetMessage (PMSG pMsg, HWND hMainWnd)
 * \brief Gets a message from the message queue of a main window.
 *
 * This function gets a message from the message queue of the main window
 * \a hMainWnd, and returns until there is a message in the message queue.
 *
 * \param pMsg Pointer to the result message.
 * \param hMainWnd Handle to the window.
 *
 * \return FALSE on MSG_QUIT have been found or on error, else gets a message.
 *
 * \sa HavePendingMessage, PostQuitMessage, MSG
 *
 * Example:
 *
 * \include getmessage.c
 */
BOOL GUIAPI GetMessage (PMSG pMsg, HWND hWnd);

/**
 * \fn int PostMessage (HWND hWnd, int iMsg, WPARAM wParam, LPARAM lParam)
 * \brief Posts a message into the message queue of a window and returns
 * immediatly.
 *
 * This functions posts a message into the message queue of the window \a hWnd
 * and returns immediately.
 *
 * \param hWnd The handle to the window.
 * \param iMsg The identifier of the message.
 * \param wParam The first parameter of the message.
 * \param lParam The second parameter of the message.
 *
 * \return ERR_OK on success, < 0 on errors.
 *
 * \retval ERR_OK Post message successfully.
 * \retval ERR_QUEUE_FULL The message queue is full.
 * \retval ERR_INV_HWND Invalid window handle.
 *
 * \sa SendMessage
 */
int GUIAPI PostMessage (HWND hWnd, int iMsg,
                WPARAM wParam, LPARAM lParam);

/**
 * \fn int SendMessage (HWND hWnd, int iMsg, WPARAM wParam, LPARAM lParam)
 * \brief Sends a message to a window.
 *
 * This function sends a message to the window \a hWnd, and will return
 * until the message-handling process returns.
 *
 * \param hWnd The handle to the window.
 * \param iMsg The identifier of the message.
 * \param wParam The first parameter of the message.
 * \param lParam The second parameter of the message.
 * \return The return value of the message handler.
 *
 * \sa PostMessage
 */
int GUIAPI SendMessage (HWND hWnd, int iMsg,
                WPARAM wParam, LPARAM lParam);

/**
 * \fn BOOL TranslateMessage (PMSG pMsg)
 * \brief Translates key down and key up messages to MSG_CHAR
 *        message and post it into the message queue.
 *
 * This function translates key down and key up message to an MSG_CHAR
 * message or some MSG_KEYSYM messages, and send the message(s) to
 * the window procedure as a notification message. If the message is
 * not a key message, this function does nothing.
 *
 * The behavior of this function is inflected by the current
 * keyboard layout. The default keyboard layout is US PC keyboard, but
 * you can call \a SetKeyboardLayout function to set a different keyboard
 * layout.
 *
 * \param pMsg The pointer of message.
 * \return A boolean indicates whether the message is a key message.
 *
 * \sa SetKeyboardLayout, MSG_CHAR, MSG_KEYSYM
 */
BOOL GUIAPI TranslateMessage (PMSG pMsg);

/**
 * \fn int DispatchMessage (PMSG pMsg)
 * \brief Dispatches a message to the window's callback procedure.
 *
 * This function dispatches the message pointed to by \a pMsg to the
 * target window's callback procedure.
 *
 * \param pMsg The pointer to the message.
 * \return The return value of the message handler.
 *
 * \sa GetMessage
 *
 * Example:
 *
 * \include getmessage.c
 */
int GUIAPI DispatchMessage (PMSG pMsg);

/**
 * \fn int ThrowAwayMessages (HWND pMainWnd)
 * \brief Removes all messages in the message queue associated with a window.
 *
 * This function removes all messages which are associated with 
 * the specified window \a pMainWnd.
 *
 * \param pMainWnd The handle to the window.
 * \return The number of thrown messages.
 *
 * \sa EmptyMessageQueue
 */
int GUIAPI ThrowAwayMessages (HWND pMainWnd);

/**
 * \fn const char* GUIAPI Message2Str (int message)
 * \brief Translates a message identifier to the message string.
 *
 * This function returns the message string of the message identifier \a message.
 * E.g. this function will return the string of "MSG_CHAR" for MSG_CHAR message.
 *
 * \param message The message identifier.
 * \return The message string.
 *
 * \note Only available if defined _MSG_STRING.
 *
 * \sa PrintMessage
 */
const char* GUIAPI Message2Str (int message);

/**
* \fn int GUIAPI InitGUI (int, const char **)
* \brief Initialize MiniGUI.
*
* The meaning of two parameters is same with parameters of main function.
*
**/
int GUIAPI InitGUI ();


/** 
* \fn void GUIAPI TerminateGUI (int rcByGUI)
* \brief Terminate MiniGUI.
*
* \param rcByGUI The flags whether close desktop thread or not.
*
**/
void GUIAPI TerminateGUI ();


#ifdef __cplusplus
}
#endif  /* __cplusplus */

#endif
